#ifndef CHATSERVICE_H
#define CHATSERVICE_H

#include <muduo/net/TcpConnection.h>
#include <unordered_map>
#include <functional>
#include <memory>    // 使用智能指针管理资源
#include <shared_mutex>    // 为了保证存储在线用户的通信连接，采用read_write lock
#include <atomic>    // for conn_count
#include <nlohmann/json.hpp>
#include "json.hpp"
#include "usermodel.hpp"
#include "offlinemessagemodel.hpp"    // 要在业务头文件加入数据库操作类
#include "friendmodel.hpp"    // for 存储好友信息
#include "groupmodel.hpp"
#include "redis/redis.hpp"

using namespace std;
using namespace muduo;
using namespace muduo::net;

using namespace placeholders;
using json = nlohmann::json;

// 处理消息的事件回调方法类型的一个别名
using MsgHandler = std::function<void(const muduo::net::TcpConnectionPtr &conn,
                                      nlohmann::json &js,
                                      muduo::Timestamp time)>;

// 聊天服务器业务类, 例如给msg_id，映射一个事件回调 <int, function<> >
class ChatService
{
public:
    // 禁止拷贝构造和赋值操作
    ChatService(const ChatService&) = delete;
    ChatService& operator=(const ChatService&) = delete;

    // 获取单例对象的静态方法
    static ChatService* getInstance();

    // 处理登陆业务
    void login(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);
    // 登录成功， 记录用户连接信息
    void add_user_connection(int id, const muduo::net::TcpConnectionPtr &conn);
    // 删除用户连接信息
    void remove_user_connection(int id);

    // 处理注册业务
    void reg(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 一对一聊天业务
    void oneChat(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 添加好友业务
    void addFriend(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 创建群组业务
    void createGroup(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 加入群组业务
    void addGroup(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 群组聊天业务
    void groupChat(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 处理注销业务
    void loginout(const muduo::net::TcpConnectionPtr &conn, nlohmann::json &js, muduo::Timestamp time);

    // 获取消息对应的处理器handler
    MsgHandler getHandler(int msgid);

    // 处理客户端异常关闭
    void clientCloseException(const std::shared_ptr<TcpConnection> &conn);

    // 服务器异常， 业务重置方法
    void resetState();

    // 从redis消息队列中获取订阅的消息
    void handleRedisSubscribeMessage(const int userid, const std::string message);

private:
    // 私有化构造函数
    ChatService();

    // 存储消息ID 和 与其对应的业务处理方法
    std::unordered_map<int, MsgHandler> _msgHandlerMap;

    // 存储在线用户的通信连接, 用户连接映射表: 随着用户的连接和断开进行插入和删除
    std::unordered_map<int, TcpConnectionPtr> _userConnMap;
    std::atomic<size_t> _connection_count; // 原子类型的连接计数器

    // 定义读写锁， 保证_userConnMap的线程安全
    std::shared_mutex _conn_rw_mutex;    // c++17

    // 数据操作类对象
    // UserModel _userModel;
    std::shared_ptr<UserModel> _userModel;    // 组合了数据库的操作类 操作都封闭在该类内
    std::shared_ptr<OfflineMsgModel> _offlineMsgModel;    // 组合一个离线消息数据库操作类
    std::shared_ptr<FriendModel> _friendModel;    // 组合一个FriendModel操作类
    std::shared_ptr<GroupModel> _groupModel;    // 群聊天业务

    // redis操作对象
    std::unique_ptr<Redis> _redis;
};

#endif






